home *** CD-ROM | disk | FTP | other *** search
/ Kit PC World De Ampliacion De Windows 95 / Kit PC World de ampliacion de Windows 95.iso / internet / sweeper / samples / docobj / framer.cpp next >
C/C++ Source or Header  |  1995-11-22  |  32KB  |  1,338 lines

  1. /*
  2.  * FRAMER.CPP
  3.  * Document Objects Framer
  4.  *
  5.  * Sample to demonstrate in-place activation of a DocObject--also
  6.  * activates normal embeddings in separate windows.
  7.  *
  8.  * Copyright (c)1995 Microsoft Corporation, All Rights Reserved
  9.  * Kraig Brockschmidt, kraigb@microsoft.com
  10.  */
  11.  
  12.  
  13. #define INITGUID
  14. #include "framer.h"
  15.  
  16.  
  17. /*
  18.  * WinMain
  19.  *
  20.  * Purpose:
  21.  *  Main entry point of application.  Should register the app class
  22.  *  if a previous instance has not done so and do any other one-time
  23.  *  initializations.
  24.  */
  25.  
  26. int PASCAL WinMain (HINSTANCE hInst, HINSTANCE hPrev
  27.     , LPSTR pszCmdLine, int nCmdShow)
  28.     {
  29.     PCFrame         pFR;    
  30.     WPARAM          wRet;
  31.  
  32.     //Attempt to allocate and initialize the application
  33.     pFR=new CFrame(hInst, hPrev, pszCmdLine, nCmdShow);
  34.  
  35.     if (NULL==pFR)
  36.         return 0;
  37.     
  38.     //If we can initialize pFR, start chugging messages
  39.     if (pFR->Init(CMENUS, CW_USEDEFAULT, CW_USEDEFAULT
  40.         , CW_USEDEFAULT, CW_USEDEFAULT))
  41.         wRet=pFR->MessageLoop();
  42.  
  43.     delete pFR;
  44.     return wRet;
  45.     }
  46.  
  47.  
  48.  
  49. /*
  50.  * CFrame::CFrame
  51.  * CFrame::~CFrame
  52.  *
  53.  * Constructor Parameters:
  54.  *  hInst           HINSTANCE from WinMain
  55.  *  hInstPrev       HINSTANCE from WinMain
  56.  *  pszCmdLine      LPSTR from WinMain
  57.  *  nCmdShow        int from WinMain
  58.  */
  59.  
  60. CFrame::CFrame(HINSTANCE hInst, HINSTANCE hInstPrev
  61.     , LPSTR pszCmdLine, int nCmdShow)    
  62.     {
  63.     m_hInst=hInst;
  64.     m_hWnd=NULL;
  65.     m_hInstPrev=hInstPrev;
  66.     m_nCmdShow=nCmdShow;
  67.  
  68.     m_phMenu=NULL;
  69.     m_hAccel=NULL;
  70.     m_hWndClient=NULL;
  71.  
  72.     m_fInitialized=FALSE;
  73.     m_pIStorage=NULL;
  74.     m_dwIDCounter=0;
  75.  
  76.     m_hMenuOrg=NULL;
  77.     m_hMenuTop=NULL;
  78.     m_hMenuHelp=NULL;
  79.     m_fInObjectHelp=FALSE;
  80.     m_fUsingOurHelp=FALSE;
  81.             
  82.     m_fHaveObject=FALSE;
  83.     m_hWndObj=NULL;
  84.  
  85.     m_pSite=NULL;
  86.     m_fOurMenuShowing=TRUE;
  87.     SetRect(&m_bwIP, 0, 0, 0, 0);
  88.     m_fInContextHelp=FALSE;
  89.     m_pIOleIPActiveObject=NULL;
  90.  
  91.     return;
  92.     }
  93.  
  94.  
  95.  
  96. CFrame::~CFrame(void)
  97.     {
  98.     if (NULL!=m_hWndClient)
  99.         DestroyWindow(m_hWndClient);
  100.     
  101.     //Frees the temp file.
  102.     ReleaseInterface(m_pIStorage);
  103.     
  104.     //m_pSite cleaned up in Close
  105.  
  106.     //Accelerators freed automatically.
  107.  
  108.     //Destroy the special help menu
  109.     if (NULL!=m_hMenuHelp)
  110.         DestroyMenu(m_hMenuHelp);
  111.  
  112.     //Free the menu handle array
  113.     if (NULL!=m_phMenu)
  114.         delete []((UINT *)m_phMenu);
  115.  
  116.     if (m_fInitialized)
  117.         OleUninitialize();
  118.  
  119.     return;
  120.     }
  121.  
  122.  
  123. /*
  124.  * CFrame::Init
  125.  *
  126.  * Purpose:
  127.  *  Initializer for a CFrame object containing anything prone to
  128.  *  failure.
  129.  *
  130.  * Parameters:
  131.  *  cMenus          UINT number of menus on the frame
  132.  *  x, y, cx, cy    int location and size of frame window 
  133.  *
  134.  * Return Value:
  135.  *  BOOL            TRUE if initialization succeeded, FALSE
  136.  *                  otherwise. If FALSE is returned, the caller must
  137.  *                  guarantee that the destructor is called promptly
  138.  *                  to insure cleanup.
  139.  */
  140.  
  141. BOOL CFrame::Init(UINT cMenus, int x, int y, int cx, int cy)
  142.     {
  143.     HMENU               hMenu;
  144.     UINT                uTemp;
  145.     RECT                rc;
  146.  
  147.     //1.  Initialize OLE
  148.     if (SUCCEEDED(OleInitialize(NULL)))
  149.         m_fInitialized=TRUE;
  150.     else
  151.         return FALSE;
  152.  
  153.  
  154.     //2.  Register window classes
  155.     if (NULL==m_hInstPrev)
  156.         {
  157.         if (!RegisterAllClasses())
  158.             return FALSE;
  159.         }
  160.  
  161.  
  162.     //3.  Create the main window and client-area window
  163.     m_hWnd=CreateWindow(SZCLASSFRAME, TEXT("DocObject Framer")
  164.         , WS_MINIMIZEBOX | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN
  165.         , x, y, cx, cy, NULL, NULL, m_hInst, this);
  166.         
  167.     if (NULL==m_hWnd)
  168.         return FALSE;
  169.  
  170.     GetClientRect(m_hWnd, &rc);
  171.  
  172.     m_hWndClient=CreateWindow(SZCLASSCLIENT, SZCLASSCLIENT
  173.         , WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | WS_CLIPSIBLINGS
  174.         , rc.left, rc.top, rc.right-rc.left
  175.         , rc.bottom-rc.top, m_hWnd, NULL, m_hInst, this);
  176.  
  177.     if (NULL==m_hWndClient)
  178.         return FALSE;
  179.  
  180.     //4. Allocate menu array for use with in-place menu merging.
  181.     m_phMenu=new HMENU[cMenus];
  182.     hMenu=GetMenu(m_hWnd);
  183.     m_hMenuOrg=hMenu;
  184.  
  185.     for (uTemp=0; uTemp < cMenus; uTemp++)
  186.         m_phMenu[uTemp]=GetSubMenu(hMenu, uTemp);
  187.  
  188.     //Also load the special help menu
  189.     m_hMenuHelp=LoadMenu(m_hInst
  190.         , MAKEINTRESOURCE(IDR_MENUHELP));
  191.  
  192.     //5.  Load accelerators
  193.     m_hAccel=LoadAccelerators(m_hInst
  194.         , MAKEINTRESOURCE(IDR_ACCELERATORS));
  195.  
  196.     if (NULL==m_hAccel)
  197.         return FALSE;
  198.  
  199.  
  200.     //6.  Make us all visible.
  201.     ShowWindow(m_hWnd, m_nCmdShow);
  202.     UpdateWindow(m_hWnd);
  203.  
  204.  
  205.     /*
  206.      * 7.  Create a temp file for all embedded files.  Note that in this
  207.      *     sample we don't save any changes to DocObjects because we 
  208.      *     don't manage any storage directly.
  209.      */      
  210.     if (FAILED(StgCreateDocfile(NULL, STGM_TRANSACTED | STGM_READWRITE
  211.         | STGM_SHARE_EXCLUSIVE | STGM_CREATE| STGM_DELETEONRELEASE
  212.         , 0, &m_pIStorage)))
  213.         return FALSE;
  214.  
  215.     return TRUE;
  216.     }
  217.  
  218.  
  219.  
  220.  
  221.  
  222. /*
  223.  * CFrame::RegisterAllClasses
  224.  *
  225.  * Purpose:
  226.  *  Registers all classes used in this application.
  227.  *
  228.  * Return Value:
  229.  *  BOOL            TRUE if registration succeeded, FALSE otherwise.
  230.  */
  231.  
  232. BOOL CFrame::RegisterAllClasses(void)
  233.     {
  234.     WNDCLASS        wc;
  235.  
  236.     //Field that are the same for all windows.
  237.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  238.     wc.hInstance     = m_hInst;
  239.     wc.cbClsExtra    = 0;
  240.  
  241.     //Register the Frame window
  242.     wc.lpfnWndProc   = FrameWndProc;
  243.     wc.cbWndExtra    = CBFRAMEWNDEXTRA;
  244.     wc.hIcon         = LoadIcon(m_hInst, TEXT("Icon"));
  245.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  246.     wc.hbrBackground = NULL;
  247.     wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MENU);
  248.     wc.lpszClassName = SZCLASSFRAME;
  249.  
  250.     if (!RegisterClass(&wc))
  251.         return FALSE;
  252.  
  253.  
  254.     //Register the do-nothing Client window
  255.     wc.lpfnWndProc   = ClientWndProc;
  256.     wc.cbWndExtra    = CBCLIENTWNDEXTRA;
  257.     wc.hIcon         = NULL;
  258.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  259.     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  260.     wc.lpszMenuName  = NULL;
  261.     wc.lpszClassName = SZCLASSCLIENT;
  262.  
  263.     if (!RegisterClass(&wc))
  264.         return FALSE;
  265.  
  266.     return TRUE;
  267.     }
  268.  
  269.  
  270.  
  271.  
  272. /*
  273.  * CFrame::OnCommand
  274.  *
  275.  * Purpose:
  276.  *  WM_COMMAND handler for the frame window so derivations can
  277.  *  process their messages and then pass the standard commands (like
  278.  *  file open and save) on to the base class.
  279.  *
  280.  * Parameters:
  281.  *  hWnd            HWND of the frame window.
  282.  *  wParam          WPARAM of the message.
  283.  *  lParam          LPARAM of the message.
  284.  *
  285.  * Return Value:
  286.  *  LRESULT         Return value for the message.
  287.  */
  288.  
  289. LRESULT CFrame::OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
  290.     {
  291.     TCHAR           szFile[MAX_PATH];
  292.     BOOL            fOK;
  293.     PCHourglass     pHour;
  294.     WORD            wID=LOWORD(wParam);
  295.  
  296.     switch (wID)
  297.         {
  298.         case IDM_FILEOPEN:
  299.             /*
  300.              * This will be disabled if we already have an object.
  301.              * User must File/Close first to get back here. 
  302.              *
  303.              * Otherwise open the File/Open dialog
  304.              */
  305.             szFile[0]=0;
  306.             if (!OpenDialog(szFile, MAX_PATH))
  307.                 return 0L;
  308.                 
  309.             pHour=new CHourglass;            
  310.             fOK=CreateObject(szFile);
  311.             delete pHour;
  312.             return 0;
  313.  
  314.  
  315.         case IDM_FILECLOSE:
  316.             Close();
  317.             break;
  318.  
  319.  
  320.         case IDM_FILEEXIT:
  321.             PostMessage(hWnd, WM_CLOSE, 0, 0L);            
  322.             break;
  323.  
  324.  
  325.         case IDM_HELPABOUT:
  326.             DialogBox(m_hInst, MAKEINTRESOURCE(IDD_ABOUT)
  327.                 , m_hWnd, (DLGPROC)AboutProc);
  328.             break;
  329.  
  330.  
  331.         case IDM_ENTERCONTEXTHELP:
  332.         case IDM_ESCAPECONTEXTHELP:
  333.             //Notify the object on entry and exit.
  334.             ContextSensitiveHelp(IDM_ENTERCONTEXTHELP==wID);
  335.             break;
  336.  
  337.  
  338.         default:
  339.            return DefWindowProc(hWnd, WM_COMMAND, wParam, lParam);
  340.                
  341.         }
  342.  
  343.     return 0L;
  344.     }
  345.  
  346.  
  347.  
  348.  
  349.  
  350. /*
  351.  * CFrame::OpenDialog
  352.  *
  353.  * Purpose:
  354.  *  Invokes the COMMDLG.DLL GetOpenFileName dialog and retrieves
  355.  *  a filename for saving or opening.
  356.  *
  357.  * Parameters:
  358.  *  pszFile         LPTSTR buffer to receive the entered filename.
  359.  *  cchFile         UINT length of pszFile 
  360.  *
  361.  * Return Value:
  362.  *  BOOL            TRUE if the function retrieved a filename,
  363.  *                  FALSE if the user pressed CANCEL.
  364.  */
  365.  
  366. BOOL CFrame::OpenDialog(LPTSTR pszFile, UINT cchFile)
  367.     {
  368.     OPENFILENAME        ofn;
  369.     static TCHAR        szFilter[80]=TEXT("All Files (*.*)\0*.*\0\0");
  370.     BOOL                fRet;
  371.    #ifdef DEBUG
  372.     DWORD               dwErr;
  373.    #endif
  374.  
  375.     if (NULL==pszFile)
  376.         return FALSE;
  377.  
  378.     memset(&ofn, 0, sizeof(OPENFILENAME));
  379.     ofn.lStructSize      =sizeof(OPENFILENAME);
  380.     ofn.hwndOwner        =m_hWnd;
  381.  
  382.     ofn.lpstrFilter      =szFilter;
  383.     ofn.nFilterIndex     =1L;
  384.  
  385.     ofn.lpstrTitle       =NULL;
  386.     ofn.lpstrFile        =pszFile;
  387.     ofn.nMaxFile         =cchFile;
  388.  
  389.     ofn.lpstrDefExt      =TEXT("*");
  390.     ofn.Flags            =OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
  391.  
  392.     fRet=GetOpenFileName(&ofn);
  393.     
  394.    #ifdef DEBUG
  395.     dwErr=CommDlgExtendedError();
  396.    #endif
  397.     return fRet;
  398.     }
  399.  
  400.  
  401.  
  402. /*
  403.  * CFrame::CreateObject
  404.  *
  405.  * Purpose:
  406.  *  Creates a site and has it create an object based on a filename.
  407.  *
  408.  * Parameters:
  409.  *  pszFile         LPTSTR pointing to the filename from which to
  410.  *                  create the object.
  411.  *
  412.  * Return Value:
  413.  *  BOOL            TRUE if successful, FALSE otherwise.
  414.  */
  415.  
  416. BOOL CFrame::CreateObject(LPTSTR pszFile)
  417.     {    
  418.     m_pSite=new CSite(++m_dwIDCounter, m_hWndClient, this);
  419.  
  420.     if (NULL==m_pSite)
  421.         return FALSE;
  422.  
  423.     m_pSite->AddRef();  //So we can free with Release
  424.  
  425.     /*
  426.      * Now tell the site to create an object in it using the filename
  427.      * and the storage we opened.  The site will create a sub-storage
  428.      * for the doc object's use.
  429.      */
  430.     if (!m_pSite->Create(pszFile, m_pIStorage))
  431.         return FALSE;
  432.  
  433.     m_fHaveObject=TRUE;
  434.  
  435.     //We created the thing, now activate it with "Show"
  436.     m_pSite->Activate(OLEIVERB_SHOW);
  437.  
  438.     //Force repaint to show "have object" message
  439.     InvalidateRect(m_hWndClient, NULL, TRUE);
  440.     UpdateWindow(m_hWndClient);
  441.     return TRUE;        
  442.     }
  443.  
  444.  
  445.  
  446. /*
  447.  * CFrame::Close
  448.  *
  449.  * Purpose:
  450.  *  Handles File/Close by freeing the object and resetting the
  451.  *  application state.
  452.  *
  453.  * Parameters:
  454.  *  None
  455.  *
  456.  * Return Value:
  457.  *  None
  458.  */
  459.  
  460. void CFrame::Close(void)
  461.     {    
  462.     RECT    rc;
  463.  
  464.     if (NULL!=m_pSite)
  465.         {
  466.         m_pSite->Close(FALSE);         //Frees the object
  467.         m_pSite->Destroy(m_pIStorage); //Cleans up the storage
  468.         m_pSite->Release();            //Frees the site
  469.         }
  470.     
  471.     m_fHaveObject=FALSE;    
  472.     SetRect(&m_bwIP, 0, 0, 0, 0);    
  473.  
  474.     GetClientRect(m_hWnd, &rc);    
  475.     ResizeClientWindow(rc.left, rc.top, rc.right-rc.left
  476.         , rc.bottom-rc.top);    
  477.  
  478.     //Force repaint to remove "have object" message
  479.     InvalidateRect(m_hWndClient, NULL, TRUE);
  480.     UpdateWindow(m_hWndClient);
  481.     
  482.     return;        
  483.     }
  484.  
  485.  
  486. /*
  487.  * CFrame::ResizeClientWindow
  488.  *
  489.  * Purpose:
  490.  *    Resizes the client-area window according to current toolbar sizes
  491.  *  and the frame window size.
  492.  *
  493.  * Parameters:
  494.  *    x,y,cx,cy        UINT origin and dimensions of the window
  495.  *
  496.  * Return Value:
  497.  *    None
  498.  */
  499.  
  500. void CFrame::ResizeClientWindow(UINT x, UINT y, UINT cx, UINT cy)
  501.     {
  502.     SetWindowPos(m_hWndClient, NULL, x, y, cx, cy        
  503.         , SWP_NOZORDER | SWP_NOACTIVATE);
  504.  
  505.     //Tell the site to tell the object.
  506.     if (NULL!=m_pSite)
  507.         m_pSite->UpdateObjectRects();
  508.  
  509.     return;
  510.     }
  511.  
  512.  
  513. /*
  514.  * CFrame::MessageLoop
  515.  *
  516.  * Purpose:
  517.  *  Spins in a standard message loop (with accelerators) until
  518.  *  WM_QUIT is found after which it returns.
  519.  *
  520.  * Return Value:
  521.  *  WPARAM          Contents of msg.wParam from WM_QUIT.
  522.  */
  523.  
  524. WPARAM CFrame::MessageLoop(void)
  525.     {
  526.     MSG     msg;
  527.  
  528.     while (GetMessage(&msg, NULL, 0,0 ))
  529.         {
  530.         //Always give the object first crack at translation.
  531.         if (NULL!=m_pIOleIPActiveObject)
  532.             {
  533.             HRESULT     hr;
  534.  
  535.             hr=m_pIOleIPActiveObject->TranslateAccelerator(&msg);
  536.  
  537.             //If the object translated the accelerator, we're done
  538.             if (NOERROR==hr)
  539.                 continue;
  540.             }
  541.  
  542.         if (!::TranslateAccelerator(m_hWnd, m_hAccel, &msg))
  543.             {
  544.             TranslateMessage(&msg);
  545.             DispatchMessage(&msg);
  546.             }
  547.         }
  548.  
  549.     return msg.wParam;
  550.     }
  551.  
  552.  
  553.  
  554. /*
  555.  * FrameWndProc
  556.  *
  557.  * Purpose:
  558.  *  Frame window class procedure that allows a derivation of these
  559.  *  classes to hook and process any messages desired.  Otherwise this
  560.  *  handles standard commands as well as the status line and menus.
  561.  */
  562.  
  563. LRESULT APIENTRY FrameWndProc(HWND hWnd, UINT iMsg
  564.     , WPARAM wParam, LPARAM lParam)
  565.     {
  566.     PCFrame         pFR;
  567.     RECT            rc;
  568.     HMENU           hMenu;
  569.  
  570.     pFR=(PCFrame)GetWindowLong(hWnd, FRAMEWL_STRUCTURE);
  571.  
  572.     switch (iMsg)
  573.         {
  574.         case WM_NCCREATE:
  575.             pFR=(PCFrame)((LPCREATESTRUCT)lParam)->lpCreateParams;
  576.  
  577.             SetWindowLong(hWnd, FRAMEWL_STRUCTURE, (LONG)pFR);
  578.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  579.  
  580.         case WM_DESTROY:
  581.             PostQuitMessage(0);
  582.             break;
  583.  
  584.         case WM_CLOSE:                        
  585.             pFR->Close();
  586.             DestroyWindow(hWnd);
  587.             break;
  588.  
  589.         case WM_ERASEBKGND:
  590.             //Client area window always manages painting
  591.             return FALSE;
  592.  
  593.         case WM_SIZE:
  594.             //Tell the in-place object about the new frame size
  595.             GetClientRect(hWnd, &rc);
  596.  
  597.             if (NULL!=pFR->m_pIOleIPActiveObject)
  598.                 pFR->m_pIOleIPActiveObject->ResizeBorder(&rc, pFR, TRUE);
  599.                     
  600.             /*
  601.              * Resize the client, which is done in all cases since this window
  602.              * is the parent of the DocObject, plus we need to tell the 
  603.              * DocObject of the new size through IOleDocumentView::SetRect.
  604.              */
  605.             rc.left  +=pFR->m_bwIP.left;
  606.             rc.right -=pFR->m_bwIP.right;
  607.             rc.top   +=pFR->m_bwIP.top;
  608.             rc.bottom-=pFR->m_bwIP.bottom;            
  609.  
  610.             pFR->ResizeClientWindow(rc.left, rc.top, rc.right-rc.left
  611.                 , rc.bottom-rc.top);
  612.             
  613.             break;
  614.  
  615.  
  616.         case WM_SETFOCUS:
  617.             if (NULL!=pFR->m_pIOleIPActiveObject)
  618.                 {
  619.                 HWND    hWndObj;
  620.  
  621.                 pFR->m_pIOleIPActiveObject->GetWindow(&hWndObj);
  622.                 SetFocus(hWndObj);
  623.                 }
  624.  
  625.             return TRUE;
  626.  
  627.  
  628.         case WM_INITMENU:
  629.             pFR->m_fInObjectHelp=FALSE;
  630.             break;
  631.  
  632.  
  633.         case WM_MENUSELECT:
  634.                 {
  635.                  UINT fuFlags=(UINT)HIWORD(wParam);
  636.                  UINT uItem=(UINT)LOWORD(wParam);
  637.  
  638.                 if (MF_POPUP & fuFlags)
  639.                     {
  640.                     /*
  641.                      * If we're inside our m_hMenuHelp, and uItem is
  642.                      * not zero (first item on the menu, which is ours),
  643.                      * then we must be in an object-supplied menu.
  644.                      *
  645.                      * Therefore we set our flag and forward the message
  646.                      * as well as others that occur later.  Otherwise we
  647.                      * clear the flag so we get messages again.
  648.                      */                
  649.                     if (NULL!=pFR->m_hMenuHelp
  650.                         && (HMENU)lParam==pFR->m_hMenuHelp)                    
  651.                         {
  652.                         pFR->m_fInObjectHelp=(0!=uItem);
  653.                 
  654.                         if (pFR->m_fInObjectHelp)
  655.                             SendMessage(pFR->m_hWndObj, iMsg, wParam, lParam);
  656.                         }                
  657.                     }
  658.                 else
  659.                     {
  660.                     //Forward the message on
  661.                     if (pFR->m_fInObjectHelp)
  662.                         {
  663.                         SendMessage(pFR->m_hWndObj, iMsg, wParam, lParam);
  664.                         break;
  665.                         }
  666.                     }        
  667.                 }
  668.             break;
  669.  
  670.         case WM_INITMENUPOPUP:
  671.             /*
  672.              * If we're in the object's Help menu, forward to
  673.              * the object received in IOleInPlaceFrame::SetActiveObject
  674.              */
  675.             if (pFR->m_fInObjectHelp && NULL!=pFR->m_hWndObj) 
  676.                 SendMessage(pFR->m_hWndObj, iMsg, wParam, lParam);
  677.  
  678.  
  679.             //Skip the system menu
  680.             if (TRUE==(BOOL)HIWORD(lParam))
  681.                 break;
  682.  
  683.             /*
  684.              * If we have an object, enable Close, otherwise
  685.              * enable Open.
  686.              */
  687.             hMenu=(HMENU)wParam;
  688.  
  689.             if (hMenu==pFR->m_phMenu[0])
  690.                 {
  691.                 UINT uTempE=MF_BYCOMMAND | MF_ENABLED;
  692.                 UINT uTempD=MF_BYCOMMAND | MF_DISABLED | MF_GRAYED;
  693.  
  694.                 EnableMenuItem(hMenu, IDM_FILEOPEN
  695.                     , pFR->m_fHaveObject ? uTempD : uTempE);
  696.                 EnableMenuItem(hMenu, IDM_FILECLOSE
  697.                     , pFR->m_fHaveObject ? uTempE : uTempD);
  698.                 }
  699.             
  700.             break;
  701.  
  702.         case WM_COMMAND:
  703.             if (pFR->m_fInObjectHelp)
  704.                 {
  705.                 SendMessage(pFR->m_hWndObj, iMsg, wParam, lParam);
  706.                 break;
  707.                 }
  708.             else
  709.                 return pFR->OnCommand(hWnd, wParam, lParam);
  710.  
  711.         default:
  712.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  713.         }
  714.  
  715.     return 0L;
  716.     }
  717.  
  718.  
  719.  
  720. /*
  721.  * ClientWndProc
  722.  *
  723.  * Purpose:
  724.  *  Client window class procedure that's only used to paint a
  725.  *  message when we have a non-DocObject open.  Otherwise this
  726.  *  is completely hidden.
  727.  */
  728.  
  729. LRESULT APIENTRY ClientWndProc(HWND hWnd, UINT iMsg
  730.     , WPARAM wParam, LPARAM lParam)
  731.     {
  732.     PCFrame         pFR;
  733.     PAINTSTRUCT        ps;
  734.  
  735.     pFR=(PCFrame)GetWindowLong(hWnd, CLIENTWL_STRUCTURE);
  736.  
  737.     switch (iMsg)
  738.         {
  739.         case WM_NCCREATE:
  740.             pFR=(PCFrame)((LPCREATESTRUCT)lParam)->lpCreateParams;
  741.  
  742.             SetWindowLong(hWnd, CLIENTWL_STRUCTURE, (LONG)pFR);
  743.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  744.  
  745.         case WM_PAINT:
  746.             BeginPaint(hWnd, &ps);
  747.  
  748.             if (pFR->m_fHaveObject)
  749.                 {
  750.                 static TCHAR szMsg[]={TEXT("A non-DocObject is open or loaded. Use File/Close to destroy it.")};
  751.  
  752.                 SetBkColor(ps.hdc, GetSysColor(COLOR_WINDOW));
  753.                 TextOut(ps.hdc, 0, 0, szMsg, lstrlen(szMsg));
  754.                 }
  755.  
  756.             EndPaint(hWnd, &ps);
  757.             break;
  758.  
  759.  
  760.         default:
  761.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  762.         }
  763.  
  764.     return 0L;
  765.     }
  766.  
  767.  
  768.  
  769.  
  770.  
  771. /*
  772.  * AboutProc
  773.  *
  774.  * Purpose:
  775.  *  Dialog procedure for the omnipresent About box.
  776.  *
  777.  * Parameters:
  778.  *  The standard.
  779.  *
  780.  * Return Value:
  781.  *  The value to be returned through the DialogBox call that
  782.  *  created the dialog.
  783.  *
  784.  */
  785.  
  786. BOOL APIENTRY AboutProc(HWND hDlg, UINT iMsg
  787.     , WPARAM wParam, LPARAM lParam)
  788.     {
  789.     switch (iMsg)
  790.         {
  791.         case WM_INITDIALOG:
  792.             return TRUE;
  793.  
  794.         case WM_COMMAND:
  795.             switch (LOWORD(wParam))
  796.                 {
  797.                 case IDOK:
  798.                     EndDialog(hDlg, TRUE);
  799.                 }
  800.             break;
  801.         }
  802.     return FALSE;
  803.     }
  804.  
  805.  
  806.  
  807.  
  808.  
  809.  
  810.  
  811.  
  812.  
  813. /*
  814.  * IOleInPlaceFrame implementation
  815.  */
  816.  
  817.  
  818. /*
  819.  * CFrame::QueryInterface
  820.  * CFrame::AddRef
  821.  * CFrame::Release
  822.  */
  823.  
  824. STDMETHODIMP CFrame::QueryInterface(REFIID riid, void **ppv)
  825.     {
  826.     //We only know IOleInPlaceFrame and it's base interfaces
  827.     *ppv=NULL;
  828.  
  829.     if (IID_IUnknown==riid || IID_IOleInPlaceUIWindow==riid
  830.         || IID_IOleWindow==riid || IID_IOleInPlaceFrame==riid)
  831.         *ppv=this;
  832.  
  833.     if (NULL!=*ppv)
  834.         {
  835.         ((LPUNKNOWN)*ppv)->AddRef();
  836.         return NOERROR;
  837.         }
  838.  
  839.     return E_NOINTERFACE;
  840.     }
  841.  
  842.  
  843. STDMETHODIMP_(ULONG) CFrame::AddRef(void)
  844.     {
  845.     return ++m_cRef;
  846.     }
  847.  
  848. STDMETHODIMP_(ULONG) CFrame::Release(void)
  849.     {
  850.     //Nothing special happening here--frame's life if user-controlled.
  851.     return --m_cRef;
  852.     }
  853.  
  854.  
  855.  
  856.  
  857. /*
  858.  * CFrame::GetWindow
  859.  *
  860.  * Purpose:
  861.  *  Retrieves the handle of the window associated with the object
  862.  *  on which this interface is implemented.
  863.  *
  864.  * Parameters:
  865.  *  phWnd           HWND * in which to store the window handle.
  866.  *
  867.  * Return Value:
  868.  *  HRESULT         NOERROR if successful, E_FAIL if there is no
  869.  *                  window.
  870.  */
  871.  
  872. STDMETHODIMP CFrame::GetWindow(HWND *phWnd)
  873.     {
  874.     *phWnd=m_hWnd;
  875.     return NOERROR;
  876.     }
  877.  
  878.  
  879.  
  880.  
  881. /*
  882.  * CFrame::ContextSensitiveHelp
  883.  *
  884.  * Purpose:
  885.  *  Instructs the object on which this interface is implemented to
  886.  *  enter or leave a context-sensitive help mode.
  887.  *
  888.  * Parameters:
  889.  *  fEnterMode      BOOL TRUE to enter the mode, FALSE otherwise.
  890.  *
  891.  * Return Value:
  892.  *  HRESULT         NOERROR
  893.  */
  894.  
  895. STDMETHODIMP CFrame::ContextSensitiveHelp(BOOL fEnterMode)
  896.     {
  897.     /*
  898.      * Don't bother if there is no active object since we don't do
  899.      * context help on our own.
  900.      */
  901.     if (NULL==m_pIOleIPActiveObject)
  902.         return NOERROR;
  903.  
  904.     //If the state changes, notify the active object.
  905.     if (m_fInContextHelp!=fEnterMode)
  906.         {
  907.         m_fInContextHelp=fEnterMode;
  908.         m_pIOleIPActiveObject->ContextSensitiveHelp(fEnterMode);
  909.         }
  910.  
  911.     return NOERROR;
  912.     }
  913.  
  914.  
  915.  
  916.  
  917. /*
  918.  * CFrame::GetBorder
  919.  *
  920.  * Purpose:
  921.  *  Returns the rectangle in which the container is willing to
  922.  *  negotiate about an object's adornments.
  923.  *
  924.  * Parameters:
  925.  *  prcBorder       LPRECT in which to store the rectangle.
  926.  *
  927.  * Return Value:
  928.  *  HRESULT         NOERROR if all is well, INPLACE_E_NOTOOLSPACE
  929.  *                  if there is no negotiable space.
  930.  */
  931.  
  932. STDMETHODIMP CFrame::GetBorder(LPRECT prcBorder)
  933.     {
  934.     if (NULL==prcBorder)
  935.         return E_INVALIDARG;
  936.  
  937.     //We return all the client area space
  938.     GetClientRect(m_hWnd, prcBorder);
  939.     return NOERROR;
  940.     }
  941.  
  942.  
  943.  
  944.  
  945. /*
  946.  * CFrame::RequestBorderSpace
  947.  *
  948.  * Purpose:
  949.  *  Asks the container if it can surrender the amount of space
  950.  *  in pBW that the object would like for it's adornments.  The
  951.  *  container does nothing but validate the spaces on this call.
  952.  *
  953.  * Parameters:
  954.  *  pBW             LPCBORDERWIDTHS containing the requested space.
  955.  *                  The values are the amount of space requested
  956.  *                  from each side of the relevant window.
  957.  *
  958.  * Return Value:
  959.  *  HRESULT         NOERROR if we can give up space,
  960.  *                  INPLACE_E_NOTOOLSPACE otherwise.
  961.  */
  962.  
  963. STDMETHODIMP CFrame::RequestBorderSpace(LPCBORDERWIDTHS pBW)
  964.     {
  965.     //Framer has no border space restrictions
  966.     return NOERROR;
  967.     }
  968.  
  969.  
  970.  
  971.  
  972. /*
  973.  * CFrame::SetBorderSpace
  974.  *
  975.  * Purpose:
  976.  *  Called when the object now officially requests that the
  977.  *  container surrender border space it previously allowed
  978.  *  in RequestBorderSpace.  The container should resize windows
  979.  *  appropriately to surrender this space.
  980.  *
  981.  * Parameters:
  982.  *  pBW             LPCBORDERWIDTHS containing the amount of space
  983.  *                  from each side of the relevant window that the
  984.  *                  object is now reserving.
  985.  *
  986.  * Return Value:
  987.  *  HRESULT         NOERROR
  988.  */
  989.  
  990. STDMETHODIMP CFrame::SetBorderSpace(LPCBORDERWIDTHS pBW)
  991.     {
  992.     RECT            rc;
  993.  
  994.     /*
  995.      * Since we have no tools, we can accept anything the object sends
  996.      * and must therefore adjust the client-area window accordingly.
  997.      */
  998.  
  999.     /*
  1000.      * If pBW is NULL, the object is not interested in tools, so we
  1001.      * don't have to do anything.  In either case we need to save
  1002.      * the toolspace allocations in order to resize the client window
  1003.      * correctly.
  1004.      */
  1005.     if (NULL==pBW)
  1006.         {
  1007.         if (!m_fOurMenuShowing)
  1008.             SetMenu(NULL, NULL, NULL);
  1009.  
  1010.         SetRect(&m_bwIP, 0, 0, 0, 0);
  1011.         return NOERROR;
  1012.         }
  1013.     else
  1014.         {
  1015.         GetClientRect(m_hWnd, &rc);
  1016.         rc.left  +=pBW->left;
  1017.         rc.right -=pBW->right;
  1018.         rc.top   +=pBW->top;
  1019.         rc.bottom-=pBW->bottom;
  1020.  
  1021.         m_bwIP=*pBW;
  1022.         }
  1023.  
  1024.     ResizeClientWindow(rc.left, rc.top, rc.right-rc.left
  1025.         , rc.bottom-rc.top);
  1026.     
  1027.     return NOERROR;
  1028.     }
  1029.  
  1030.  
  1031.  
  1032.  
  1033. /*
  1034.  * CFrame::SetActiveObject
  1035.  *
  1036.  * Purpose:
  1037.  *  Provides the container with the object's IOleInPlaceActiveObject
  1038.  *  pointer
  1039.  *
  1040.  * Parameters:
  1041.  *  pIIPActiveObj   LPOLEINPLACEACTIVEOBJECT of interest.
  1042.  *  pszObj          LPCOLESTR naming the object.  Not used.
  1043.  *
  1044.  * Return Value:
  1045.  *  HRESULT         NOERROR
  1046.  */
  1047.  
  1048. STDMETHODIMP CFrame::SetActiveObject
  1049.     (LPOLEINPLACEACTIVEOBJECT pIIPActiveObj, LPCOLESTR pszObj)
  1050.     {
  1051.     if (NULL!=m_pIOleIPActiveObject)
  1052.         m_pIOleIPActiveObject->Release();
  1053.  
  1054.     //NULLs m_pIOleIPActiveObject if pIIPActiveObj is NULL
  1055.     m_pIOleIPActiveObject=pIIPActiveObj;
  1056.  
  1057.     if (NULL!=m_pIOleIPActiveObject)
  1058.         m_pIOleIPActiveObject->AddRef();
  1059.  
  1060.     m_pIOleIPActiveObject->GetWindow(&m_hWndObj);
  1061.     return NOERROR;
  1062.     }
  1063.  
  1064.  
  1065.  
  1066.  
  1067. /*
  1068.  * CFrame::InsertMenus
  1069.  *
  1070.  * Purpose:
  1071.  *  Instructs the container to place its in-place menu items where
  1072.  *  necessary in the given menu and to fill in elements 0, 2, and 4
  1073.  *  of the OLEMENUGROUPWIDTHS array to indicate how many top-level
  1074.  *  items are in each group.
  1075.  *
  1076.  * Parameters:
  1077.  *  hMenu           HMENU in which to add popups.
  1078.  *  pMGW            LPOLEMENUGROUPWIDTHS in which to store the
  1079.  *                  width of each container menu group.
  1080.  *
  1081.  * Return Value:
  1082.  *  HRESULT         NOERROR
  1083.  */
  1084.  
  1085. STDMETHODIMP CFrame::InsertMenus(HMENU hMenu
  1086.     , LPOLEMENUGROUPWIDTHS pMGW)
  1087.     {    
  1088.     //Copy our File menu into the shared menu.    
  1089.     InsertMenu(hMenu, 0, MF_BYPOSITION | MF_POPUP, (UINT)m_phMenu[0]
  1090.         , TEXT("&File"));
  1091.  
  1092.     pMGW->width[0]=1;
  1093.     pMGW->width[2]=0;
  1094.     pMGW->width[4]=0;
  1095.  
  1096.     /*
  1097.      * Add the special help menu which is the first item in
  1098.      * the m_hMenuHelp popup that's sitting around.
  1099.      */
  1100.     InsertMenu(hMenu, 1, MF_BYPOSITION | MF_POPUP
  1101.         , (UINT)m_hMenuHelp, TEXT("&Help"));
  1102.  
  1103.     //Tell the object we added our Help menu
  1104.     pMGW->width[5]=1;    
  1105.     return NOERROR;
  1106.     }
  1107.  
  1108.  
  1109.  
  1110.  
  1111. /*
  1112.  * CFrame::SetMenu
  1113.  *
  1114.  * Purpose:
  1115.  *  Instructs the container to replace whatever menu it's currently
  1116.  *  using with the given menu and to call OleSetMenuDescritor so OLE
  1117.  *  knows to whom to dispatch messages.
  1118.  *
  1119.  * Parameters:
  1120.  *  hMenu           HMENU to show.
  1121.  *  hOLEMenu        HOLEMENU to the menu descriptor.
  1122.  *  hWndObj         HWND of the active object to which messages are
  1123.  *                  dispatched.
  1124.  *
  1125.  * Return Value:
  1126.  *  HRESULT         NOERROR
  1127.  */
  1128.  
  1129. STDMETHODIMP CFrame::SetMenu(HMENU hMenu, HOLEMENU hOLEMenu
  1130.     , HWND hWndObj)
  1131.     {
  1132.     HRESULT         hr;
  1133.  
  1134.     /*
  1135.      * Our responsibilities here are to put the menu on the frame
  1136.      * window and call OleSetMenuDescriptor.
  1137.      */
  1138.  
  1139.     if (NULL==hMenu)
  1140.         {
  1141.         //Prevent redundant calls, or debug warnings on startup.
  1142.         if (NULL==m_hMenuTop)
  1143.             return NOERROR;
  1144.  
  1145.         hMenu=m_hMenuTop;
  1146.         m_hMenuTop=NULL;
  1147.         m_fOurMenuShowing=TRUE;
  1148.         }
  1149.     else
  1150.         {
  1151.         m_hMenuTop=m_hMenuOrg;
  1152.         m_fOurMenuShowing=FALSE;
  1153.  
  1154.         /*
  1155.          * Check if our Help menu has anything added to it.  If so, then
  1156.          * remember to forward menu messages.  If not, remove the Help
  1157.          * menu altogether (destroying it after removing our normal Help
  1158.          * popup, as we also do in RemoveMenus.
  1159.          */
  1160.         if (CHELPITEMS!=GetMenuItemCount(m_hMenuHelp))
  1161.             m_fUsingOurHelp=TRUE;
  1162.         else
  1163.             {            
  1164.             UINT    i, cItems;
  1165.                 
  1166.             cItems=GetMenuItemCount(hMenu);            
  1167.  
  1168.             //Find m_hMenuHelp in the menu and remove it.
  1169.             for (i=0; i < cItems; i++)
  1170.                 {
  1171.                 if (GetSubMenu(hMenu, i)==m_hMenuHelp)
  1172.                     {
  1173.                     RemoveMenu(hMenu, i, MF_BYPOSITION);
  1174.                     break;
  1175.                     }
  1176.                 }                            
  1177.             }            
  1178.         }
  1179.  
  1180.     if (NULL!=hMenu)
  1181.         ::SetMenu(m_hWnd, hMenu);
  1182.  
  1183.     DrawMenuBar(m_hWnd);
  1184.  
  1185.     hr=OleSetMenuDescriptor(hOLEMenu, m_hWnd, hWndObj, NULL, NULL);
  1186.     return hr;
  1187.     }
  1188.  
  1189.  
  1190.  
  1191.  
  1192. /*
  1193.  * CFrame::RemoveMenus
  1194.  *
  1195.  * Purpose:
  1196.  *  Asks the container to remove any menus it put into hMenu in
  1197.  *  InsertMenus.
  1198.  *
  1199.  * Parameters:
  1200.  *  hMenu           HMENU from which to remove the container's
  1201.  *                  items.
  1202.  *
  1203.  * Return Value:
  1204.  *  HRESULT         NOERROR
  1205.  */
  1206.  
  1207. STDMETHODIMP CFrame::RemoveMenus(HMENU hMenu)
  1208.     {
  1209.     int         cItems, i, j;
  1210.     HMENU       hMenuT;
  1211.  
  1212.     /*
  1213.      * To be defensive, loop through this menu removing anything
  1214.      * we recognize (that is, anything in m_phMenu) just in case
  1215.      * the server didn't clean it up right.  At least we can
  1216.      * give ourselves the prophylactic benefit.
  1217.      */
  1218.  
  1219.     if (NULL==hMenu)
  1220.         return NOERROR;
  1221.  
  1222.     cItems=GetMenuItemCount(hMenu);
  1223.  
  1224.     /*
  1225.      * Walk backwards down the menu.  For each popup, see if it
  1226.      * matches any other popup we know about, and if so, remove
  1227.      * it from the shared menu.
  1228.      */
  1229.     for (i=cItems; i >=0; i--)
  1230.         {
  1231.         hMenuT=GetSubMenu(hMenu, i);
  1232.  
  1233.         for (j=0; j <= CMENUS; j++)
  1234.             {
  1235.             //Remove any owned popup, or our special help menu
  1236.             if (hMenuT==m_phMenu[j]
  1237.                 || (hMenuT==m_hMenuHelp && m_hMenuHelp!=NULL))
  1238.                 RemoveMenu(hMenu, i, MF_BYPOSITION);
  1239.             }
  1240.         }
  1241.     
  1242.     m_fUsingOurHelp=FALSE;
  1243.  
  1244.     //The menu should now be empty.
  1245.     return NOERROR;
  1246.     }
  1247.  
  1248.  
  1249.  
  1250.  
  1251. /*
  1252.  * CFrame::SetStatusText
  1253.  *
  1254.  * Purpose:
  1255.  *  Asks the container to place some text in a status line, if one
  1256.  *  exists.  If the container does not have a status line it
  1257.  *  should return E_FAIL here in which case the object could
  1258.  *  display its own.
  1259.  *
  1260.  * Parameters:
  1261.  *  pszText         LPCOLESTR to display.
  1262.  *
  1263.  * Return Value:
  1264.  *  HRESULT         NOERROR if successful, S_TRUNCATED if not all
  1265.  *                  of the text could be displayed, or E_FAIL if
  1266.  *                  the container has no status line.
  1267.  */
  1268.  
  1269. STDMETHODIMP CFrame::SetStatusText(LPCOLESTR pszText)
  1270.     {
  1271.     //We have no status line...
  1272.     return E_NOTIMPL;
  1273.     }
  1274.  
  1275.  
  1276.  
  1277. /*
  1278.  * CFrame::EnableModeless
  1279.  *
  1280.  * Purpose:
  1281.  *  Instructs the container to show or hide any modeless popup
  1282.  *  windows that it may be using.
  1283.  *
  1284.  * Parameters:
  1285.  *  fEnable         BOOL indicating to enable/show the windows
  1286.  *                  (TRUE) or to hide them (FALSE).
  1287.  *
  1288.  * Return Value:
  1289.  *  HRESULT         NOERROR
  1290.  */
  1291.  
  1292. STDMETHODIMP CFrame::EnableModeless(BOOL fEnable)
  1293.     {
  1294.     return NOERROR;
  1295.     }
  1296.  
  1297.  
  1298.  
  1299.  
  1300. /*
  1301.  * CFrame::TranslateAccelerator
  1302.  *
  1303.  * Purpose:
  1304.  *  When dealing with an in-place object from an EXE server, this
  1305.  *  is called to give the container a chance to process accelerators
  1306.  *  after the server has looked at the message.
  1307.  *
  1308.  * Parameters:
  1309.  *  pMSG            LPMSG for the container to examine.
  1310.  *  wID             WORD the identifier in the container's
  1311.  *                  accelerator table (from IOleInPlaceSite
  1312.  *                  ::GetWindowContext) for this message (OLE does
  1313.  *                  some translation before calling).
  1314.  *
  1315.  * Return Value:
  1316.  *  HRESULT         NOERROR if the keystroke was used,
  1317.  *                  S_FALSE otherwise.
  1318.  */
  1319.  
  1320. STDMETHODIMP CFrame::TranslateAccelerator(LPMSG pMSG, WORD wID)
  1321.     {
  1322.     /*
  1323.      * wID already has anything translated from m_hAccel for us,
  1324.      * so we can just check for the commands we want and process
  1325.      * them instead of calling TranslateAccelerator which would be
  1326.      * redundant and which also has a possibility of dispatching to
  1327.      * the wrong window.
  1328.      */
  1329.     if (IDM_ENTERCONTEXTHELP==wID || IDM_ESCAPECONTEXTHELP==wID)
  1330.         {
  1331.         //wID properly expands to 32-bits
  1332.         OnCommand(m_hWnd, (WPARAM)wID, 0L);
  1333.         return NOERROR;
  1334.         }
  1335.  
  1336.     return S_FALSE;
  1337.     }
  1338.